图解源码之java锁的获取和释放(AQS)篇
补充threadLocal内存泄露问题
threadLocal总结:
1.为什么会泄露:,
由于ThreadLocalMap的生命周期跟Thread一样长,在Thread周期内 ,ThreadLocalMap 中key,value对象只增不减,如果都没有手动删除对应key,都会导致内存泄漏,但是jvm提供的一层保障。
2,jvm如何通过弱引用给我们提供了一层保障
设置ThreadLocalMap的key ThreadLocal对象为弱引用,当key不在被引用时,下次gc回收的时候threadlocal将被回收(即threadLocalMap的key被变为null)
当调用threadLocal,的get,set,remove方法时会清除threadLocalMap的key为空的对象,至此key,value都被回收,不会发生内存泄露
3,为什么jvm提供了保障还会出现内存泄露
线程长时间运行,比如在线程池里的线程,ThreadLocalMap 产生了大量key为null,的value对象,而又没有调用get,set,remove方法,以至于没有回收这些对象导致,
故ThreadLocal使用后务必调用remove方法,以防止内存泄露。
以独占式不公平锁为例,通过5个线程争夺ReentrantLock的过程,图解ReentrantLock源码实现,了解显示锁的工作流程。
任何时刻拿到锁的只有一个线程,未拿到锁的线程会打包成节点(node),然后将节点通过CAS自旋的方式,从队列尾部放入同步队列中。
增加尾节点为什么要用cas,因为会存在多个线程竞争尾节点。
以上便是线程竞争锁的过程,以及竞争失败之后需要做的全部事情。
以上便是线程获取和释放锁的全过程,可用如下流程图进行归纳。
另外,以上源码均来自jdk1.8,本文章作为梳理思路,仅摘要了关键部分,详细流程请读者跟着思路自行阅读源码,英文过关是阅读的必要技能之一,不然看不懂注释真的很蛋疼。。重要的事情说三遍,英文一定要好!
英文一定要好!英文一定要好!